package org.meproj.cloudscale.monitoring;

import org.meproj.cloudscale.cloud.CloudController;
import org.meproj.cloudscale.sla.LoadSLA;
import org.meproj.cloudscale.sla.SlaDTO;
import org.meproj.cloudscale.utils.Constants;

public class ListenResourceLoad {

	private int countOfVms;
	//private String userId;
	private float cpuAvg;
	private float memoryAvg;
	private SlaDTO slaDTO = null;
	
	public ListenResourceLoad(String userId, int countOfVms ) {
		super();
		this.countOfVms = countOfVms;
		//this.userId = userId;
		slaDTO = LoadSLA.getSla(userId);
		
		cpuAvg = 0f;
		memoryAvg = 0f;
		
	}

	/** 
	 * This function will be called in fixed frequency with CPU details 
	 * @param resourceUtilizationDTO
	 */
	
	public void listen(ResourceUtilizationDTO resourceUtilizationDTO) {
		
		// calculate average for cpu and memory
		if(cpuAvg != 0 ) {
			cpuAvg = ( cpuAvg + resourceUtilizationDTO.getCpuPercent() ) / 2;
			memoryAvg = (memoryAvg + resourceUtilizationDTO.getMemoryLeft()) / 2;
		} else {
			cpuAvg = resourceUtilizationDTO.getCpuPercent();
			memoryAvg = resourceUtilizationDTO.getMemoryLeft();
		}
		
		
		float violationDegreeForCPU = checkSlaViolationForCPU(cpuAvg);
		float violationDegreeForMemory = checkSlaViolationForMemory(memoryAvg);
		
		CloudController cloudController = new CloudController(resourceUtilizationDTO.getVirtualMachineNameorIP());
		
		
		if(violationDegreeForCPU >= 0) { 
		
			cloudController.accomodateResourceIncrease(Constants.violationDegreeForCPU, violationDegreeForCPU);
			
		} else if(violationDegreeForMemory >= 0) { 
		
			cloudController.accomodateResourceIncrease(Constants.violationDegreeForMemory, violationDegreeForMemory);
		}
	}
	
	/**
	 * 
	 * @param resourceUtilizationDTO 
	 * @return violationDegree (if < 1 then about to be violated. 
	 * if = 0 then being violated. 
	 * If > 0 then has already being violated) 
	 * Calculation will be done based on Risk Appetite of SLA
	 */
	
	protected float checkSlaViolationForCPU(float cpuPercent) {
		float violationDegree = -1;
		
		float cpuPercentDiff = violationDegree = cpuPercent - slaDTO.getIncreaseAFterResource().getCpuPercent();
		
		if(cpuPercentDiff < 0) {
			
			float probabilityPercent = ((cpuPercentDiff * -1) 
					                    / slaDTO.getIncreaseAFterResource().getCpuPercent() ) 
					                    * 100;
			
			if(probabilityPercent>=slaDTO.getRiskAppetite()) {
				violationDegree = probabilityPercent;
			} 
		} 
				
		return violationDegree;
	}
	
	/**
	 * 
	 * @param resourceUtilizationDTO 
	 * @return violationDegree (if < 1 then about to be violated. 
	 * if = 0 then being violated. 
	 * If > 0 then has already being violated) 
	 * Calculation will be done based on Risk Appetite of SLA
	 */
	
	protected float checkSlaViolationForMemory(float memoryLeft) {
		
		float violationDegree = -1;
		
		float memPercentDiff = violationDegree = memoryLeft - slaDTO.getIncreaseAFterResource().getMemoryLeft();
		
		if(memPercentDiff < 0) {
			
			float probabilityPercent = ((memPercentDiff * -1) 
					                    / slaDTO.getIncreaseAFterResource().getMemoryLeft() ) 
					                    * 100;
			
			if(probabilityPercent>=slaDTO.getRiskAppetite()) {
				violationDegree = probabilityPercent;
			} 
		} 
				
		return violationDegree;
	}

	public int getCountOfVms() {
		return countOfVms;
	}

	public void setCountOfVms(int countOfVms) {
		this.countOfVms = countOfVms;
	}

	public float getCpuAvg() {
		return cpuAvg;
	}

	public void setCpuAvg(float cpuAvg) {
		this.cpuAvg = cpuAvg;
	}

	public float getMemoryAvg() {
		return memoryAvg;
	}

	public void setMemoryAvg(float memoryAvg) {
		this.memoryAvg = memoryAvg;
	}
}
